package com.example.high_slope_electronic_sand_table.slopeDisplacement.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.example.high_slope_electronic_sand_table.common.constant.DataClassificationConstant;
import com.example.high_slope_electronic_sand_table.common.constant.GeneralConstants;
import com.example.high_slope_electronic_sand_table.common.util.WeightRandomUtil;
import com.example.high_slope_electronic_sand_table.slopeDisplacement.Enum.UndergroundWaterLevelWarningEnum;
import com.example.high_slope_electronic_sand_table.slopeDisplacement.dto.UndergroundWaterLevelMonitorDTO;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UndergroundWaterLevelMonitorService {
    private final static String DEVICE_SN_MIDDLE = "0ILM0"; // 设备编码中段

    private final static Integer MAX_SIZE = 30; // 最大数据条数

    private static Map<String, List<UndergroundWaterLevelMonitorDTO>> undergroundWaterLevelDataMap = new HashMap<>();

    /**
     * 查询单条边坡位移监测-地下水位监测数据
     *
     * @return
     */
    public UndergroundWaterLevelMonitorDTO getCurrentMonitorData(String deviceId) {
        if (!undergroundWaterLevelDataMap.containsKey(deviceId) || undergroundWaterLevelDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        // 获取当前的时间和当前设备数据最后一条时间比较，如果当前时间比数据最后一条时间大于等于10分钟，则重新生成一条数据放在列表最后。如果小于十分钟，返回最后一条数据
        LocalDateTime currentDateTime = LocalDateTime.now();
        UndergroundWaterLevelMonitorDTO undergroundWaterLevelMonitorDTO = undergroundWaterLevelDataMap.get(deviceId).get(MAX_SIZE - 1);
        LocalDateTime lastDateTime = LocalDateTime.parse(undergroundWaterLevelMonitorDTO.getDatetime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
        Duration duration = Duration.between(lastDateTime, currentDateTime);
        if (duration.toMinutes() >= GeneralConstants.GENERATOR_DATA_DURATION_TIME) {
            for (int item = 1; item <= duration.toMinutes() / GeneralConstants.GENERATOR_DATA_DURATION_TIME; item++) {
                Date newDate = DateUtil.offset(Date.from(lastDateTime.atZone(ZoneId.systemDefault()).toInstant()), DateField.MINUTE, +item * GeneralConstants.GENERATOR_DATA_DURATION_TIME); // 最后一条时间向后推10分钟
                undergroundWaterLevelDataMap.get(deviceId).add(generatorMonitorData(deviceId, DateUtil.format(newDate, DatePattern.NORM_DATETIME_PATTERN)));
                undergroundWaterLevelDataMap.get(deviceId).remove(0);
            }
            return undergroundWaterLevelDataMap.get(deviceId).get(MAX_SIZE - 1);
        }else {
            return undergroundWaterLevelMonitorDTO;
        }
    }

    /**
     * 查询某个设备所有边坡位移监测-地下水位监测数据
     *
     * @return
     */
    public List<UndergroundWaterLevelMonitorDTO> listMonitorDataByDeviceId(@PathVariable String deviceId) {
        if (!undergroundWaterLevelDataMap.containsKey(deviceId) || undergroundWaterLevelDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        return undergroundWaterLevelDataMap.get(deviceId).stream().sorted(Comparator.comparing(UndergroundWaterLevelMonitorDTO::getDatetime).reversed()).collect(Collectors.toList());
    }

    /**
     * 查询某个设备所有边坡位移监测-地下水位监测告警数据
     *
     * @return
     */
    public List<UndergroundWaterLevelMonitorDTO> listWarningMonitorDataByDeviceId(@PathVariable String deviceId) {
        if (!undergroundWaterLevelDataMap.containsKey(deviceId) || undergroundWaterLevelDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        return undergroundWaterLevelDataMap.get(deviceId)
                .stream().sorted(Comparator.comparing(UndergroundWaterLevelMonitorDTO::getDatetime).reversed())
                .filter(undergroundWaterLevelMonitorDTO -> undergroundWaterLevelMonitorDTO.getUndergroundWaterLevelWarningLevel() != 0)
                .collect(Collectors.toList());
    }


    /**
     * 查询多条边坡位移监测-地下水位监测数据
     *
     * @return
     */
    public List<UndergroundWaterLevelMonitorDTO> listMonitorData() {
        List<UndergroundWaterLevelMonitorDTO> undergroundWaterLevelMonitorDTOS = new ArrayList<>();
        if (undergroundWaterLevelDataMap.isEmpty()) {
            // 生成3个设备相关数据
            for (int index = 0; index < GeneralConstants.GENERATOR_DEVICE_NUMBER; index++) {
                String deviceId = GeneralConstants.DEVICE_SN_PREFIX + DEVICE_SN_MIDDLE + index;
                batchGeneratorMonitorDataS(deviceId);
            }
        }
        for (String deviceId : undergroundWaterLevelDataMap.keySet()) {
            undergroundWaterLevelMonitorDTOS.addAll(undergroundWaterLevelDataMap.get(deviceId));
        }
        return undergroundWaterLevelMonitorDTOS.stream().sorted(Comparator.comparing(UndergroundWaterLevelMonitorDTO::getDatetime).reversed()).collect(Collectors.toList());
    }

    /**
     * 批量生成边坡位移监测-地下水位监测数据
     *
     * @param deviceId
     */
    private void batchGeneratorMonitorDataS(String deviceId) {
        List<UndergroundWaterLevelMonitorDTO> undergroundWaterLevelMonitorDTOS = new ArrayList<>(MAX_SIZE);
        for (int item = 1; item <= MAX_SIZE; item++) {
            Date date = DateUtil.date();
            Date newDate = DateUtil.offset(date, DateField.MINUTE, -(MAX_SIZE - item) * GeneralConstants.GENERATOR_DATA_DURATION_TIME); // 当前时间向前推item*10分钟
            undergroundWaterLevelMonitorDTOS.add(generatorMonitorData(deviceId, DateUtil.format(newDate, DatePattern.NORM_DATETIME_PATTERN)));
        }
        undergroundWaterLevelDataMap.put(deviceId, undergroundWaterLevelMonitorDTOS);
    }

    /**
     * 生成边坡位移监测-地下水位监测数据
     *
     * @param deviceId
     * @param dateTime
     * @return
     */
    private UndergroundWaterLevelMonitorDTO generatorMonitorData(String deviceId, String dateTime) {
        UndergroundWaterLevelMonitorDTO undergroundWaterLevelMonitorDTO = new UndergroundWaterLevelMonitorDTO();
        undergroundWaterLevelMonitorDTO.setDeviceId(deviceId);
        // 生成权重随机数
        Float undergroundWaterLevelValue = WeightRandomUtil.getWeightRandomValue(UndergroundWaterLevelWarningEnum.WARNING_ONE.getValue(),
                UndergroundWaterLevelWarningEnum.WARNING_TWO.getValue(), UndergroundWaterLevelWarningEnum.WARNING_THREE.getValue(),
                0f, 1.5f);
        undergroundWaterLevelMonitorDTO.setUndergroundWaterLevel(undergroundWaterLevelValue);
        undergroundWaterLevelMonitorDTO.setDatetime(dateTime);
        checkWarningLevel(undergroundWaterLevelMonitorDTO);
        return undergroundWaterLevelMonitorDTO;
    }

    /**
     * 判断告警等级
     *
     * @param undergroundWaterLevelMonitorDTO
     */
    private void checkWarningLevel(UndergroundWaterLevelMonitorDTO undergroundWaterLevelMonitorDTO) {
        // 浸润水位
        Optional<UndergroundWaterLevelWarningEnum> undergroundWaterLevelFirst = DataClassificationConstant.undergroundWaterLevelWarningList.stream()
                .filter(undergroundWaterLevelWarning -> undergroundWaterLevelMonitorDTO.getUndergroundWaterLevel() >= undergroundWaterLevelWarning.getValue())
                .findFirst();
        undergroundWaterLevelMonitorDTO.setUndergroundWaterLevelWarningLevel(
                undergroundWaterLevelFirst.isEmpty() || ObjectUtil.isEmpty(undergroundWaterLevelFirst.get()) ? 0 : undergroundWaterLevelFirst.get().getWarningLevel());
    }
}
